'use client';

import type { TMetadata } from '@/types';
import { useSearchParams } from 'next/navigation';
import { useInfiniteQuery } from '@tanstack/react-query';
import { clientQuerySectionDetailsById } from '@/services/api';
import type {
  IPost,
  IQueryParams,
  ISectionDetails,
  ITag,
  ITagGroup,
  IUser,
} from '@/interfaces';
import Link from 'next/link';
import classNames from 'classnames';
import LoadPage from '@/app/[locale]/load/load';
import ErrorPage from '@/app/[locale]/error/error';
import { formatCount, toRelativeTime } from '@/lib/tool';
import { useEffect, useState } from 'react';
import { NavbarPage } from '@/app/[locale]/navbar';
import FooterPage from '@/app/[locale]/footer';
import useToast from '@/hooks/useToast';
import useContentLayer from '@/hooks/useContentLayer';
import Nodata from '@/app/[locale]/common/nodata/nodata';
import PostName from '@/app/[locale]/common/post/name';
import { useTranslations } from 'use-intl';

export default function SectionIdPage({ metadata }: { metadata: TMetadata }) {
  return (
    <>
      <NavbarPage metadata={metadata} />
      <SectionId metadata={metadata} />
      <FooterPage metadata={metadata} />
    </>
  );
}

const SectionId = ({ metadata }: { metadata: TMetadata }) => {
  const { show } = useToast();
  const [isClickLoadMore, setIsClickLoadMore] = useState(false);
  const [pages, setPages] = useState<IPost[]>(
    (metadata.all['sectionId'].v as ISectionDetails).data?.content ?? [],
  );

  const clientQuerySectionDetailsByIdQuery = useInfiniteQuery(
    metadata.all['sectionId'].k,
    async (context) => {
      return (await clientQuerySectionDetailsById({
        id: context.queryKey[3],
        query: {
          ...(context.queryKey[5] as IQueryParams),
          ...context.pageParam,
        },
      })) as ISectionDetails;
    },
    {
      enabled: isClickLoadMore,
      keepPreviousData: true,
      getPreviousPageParam: (firstPage) => {
        if (firstPage.data && firstPage.data.pageable.previous) {
          return {
            page: Math.max(firstPage.data.pageable.page - 1, 0),
          };
        }
      },
      getNextPageParam: (lastPage) => {
        if (lastPage.data && lastPage.data.pageable.next) {
          return {
            page: Math.min(
              lastPage.data.pageable.page + 1,
              lastPage.data.pageable.pages,
            ),
          };
        }
      },
      initialData: () => {
        if (metadata.all['sectionId']) {
          return {
            pages: [metadata.all['sectionId'].v as ISectionDetails],
            pageParams: [
              {
                page: Math.max(
                  ((metadata.all['sectionId'].k[5] as IQueryParams).page ?? 1) -
                    1,
                  0,
                ),
              },
            ],
          };
        }
      },
    },
  );

  useEffect(() => {
    if (clientQuerySectionDetailsByIdQuery.data) {
      setPages(
        clientQuerySectionDetailsByIdQuery.data.pages
          .flatMap((item) => item.data?.content ?? [])
          .map((item) => {
            item._contentUpdatedOnText = toRelativeTime(item.contentUpdatedOn);
            return item;
          }),
      );
    }
  }, [clientQuerySectionDetailsByIdQuery.data]);

  async function onClickLoadMore() {
    setIsClickLoadMore(true);

    try {
      await clientQuerySectionDetailsByIdQuery.fetchNextPage();
    } catch (e) {
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  if (clientQuerySectionDetailsByIdQuery.data) {
    const sectionData = clientQuerySectionDetailsByIdQuery.data.pages[0];

    return (
      <div className="col">
        <div className="vstack gap-4">
          <Top
            name={sectionData.basic.name}
            content={sectionData.content}
            admins={sectionData.admins}
            metadata={metadata}
          />

          <div className="card border-0">
            <div className="card-body">
              <div className="vstack gap-4">
                <TagGroups
                  id={sectionData.basic.id}
                  items={sectionData.tagGroups}
                />

                <Tags id={sectionData.basic.id} items={sectionData.tags} />

                {pages.length > 0 ? (
                  <>
                    <Table items={pages} />

                    <LoadMoreBtn
                      isDisabled={
                        !clientQuerySectionDetailsByIdQuery.hasNextPage ||
                        clientQuerySectionDetailsByIdQuery.isFetchingNextPage
                      }
                      isFetchingNextPage={
                        clientQuerySectionDetailsByIdQuery.isFetchingNextPage
                      }
                      onClickLoadMore={onClickLoadMore}
                    />
                  </>
                ) : (
                  <Nodata />
                )}
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }

  if (clientQuerySectionDetailsByIdQuery.error) {
    return <ErrorPage error={clientQuerySectionDetailsByIdQuery.error} />;
  }

  return <LoadPage />;
};

const Top = ({
  name,
  content,
  admins,
  metadata,
}: {
  name: string;
  content: string | undefined;
  admins: IUser[];
  metadata: TMetadata;
}) => {
  const t = useTranslations('SectionIdPage');

  useContentLayer({
    dep: content,
    metadata,
  });

  return (
    <div className="card border-0">
      <div className="card-body">
        <h1
          className="fs-4 card-title d-flex align-items-center mb-4"
          title={name}
        >
          <span>{name}</span>
        </h1>

        <div
          className="content-layer"
          dangerouslySetInnerHTML={{ __html: content || '' }}
        />

        <div className="card-subtitle d-flex justify-content-end text-muted mt-4">
          {admins.map((item, index) => {
            return (
              <div key={item.id}>
                <Link
                  href={`/users/${item.id}`}
                  className="text-muted link-underline link-offset-2 link-underline-opacity-0 link-underline-opacity-100-hover"
                >
                  {item.alias}
                </Link>
                {index !== admins.length - 1 && '、'}
              </div>
            );
          })}
        </div>
        <p className="text-end card-text text-muted">{t('admin')}</p>
      </div>
    </div>
  );
};

const TagGroups = ({ id, items = [] }: { id: number; items?: ITagGroup[] }) => {
  const urlSearchParams = useSearchParams();
  const activeTagGroupIndex =
    urlSearchParams.get('tagGroupId') || urlSearchParams.get('tgId');
  const activeTagIndex =
    urlSearchParams.get('tagId') || urlSearchParams.get('tId');

  return (
    <>
      {items.length > 0 && (
        <>
          {items.map((item) => {
            return (
              <div key={item.id} className="hstack gap-3 mb-3">
                <Link
                  href={`/sections/${id}`}
                  className="badge text-bg-light fs-6 text-decoration-none fw-normal text-decoration-underline-hover"
                >
                  {item.name}
                </Link>

                {(item.tags || []).map((item2) => {
                  return (
                    <Link
                      key={item2.id}
                      href={`/sections/${id}?tagGroupId=${item.id}&tagId=${item2.id}`}
                      className={classNames(
                        'badge fs-6 text-decoration-none fw-normal text-decoration-underline-hover',
                        activeTagGroupIndex === item.id + '' &&
                          activeTagIndex === item2.id + ''
                          ? 'text-bg-secondary'
                          : 'text-bg-light',
                      )}
                    >
                      {item2.name}
                    </Link>
                  );
                })}
              </div>
            );
          })}
        </>
      )}
    </>
  );
};

const Tags = ({ id, items = [] }: { id: number; items?: ITag[] }) => {
  const urlSearchParams = useSearchParams();
  const activeTagIndex =
    urlSearchParams.get('tagId') || urlSearchParams.get('tId');
  const t = useTranslations('SectionIdPage');

  return (
    <div className="hstack gap-3">
      <Link
        href={`/sections/${id}`}
        className="badge text-bg-light fs-6 fw-normal link-underline link-offset-2 link-underline-opacity-0 link-underline-opacity-100-hover"
      >
        {t('all')}
      </Link>

      {items.map((item) => {
        return (
          <Link
            key={item.id}
            href={`/sections/${id}?tagId=${item.id}`}
            className={classNames(
              'badge fs-6 fw-normal link-underline link-offset-2 link-underline-opacity-0 link-underline-opacity-100-hover',
              activeTagIndex === item.id + ''
                ? 'text-bg-primary'
                : 'text-bg-light',
            )}
          >
            {item.name}
          </Link>
        );
      })}
    </div>
  );
};

const Table = ({ items = [] }: { items?: IPost[] }) => {
  const t = useTranslations('SectionIdPage');

  return (
    <div className="table-responsive mt-5 mb-4">
      <table className="table table-hover table-borderless align-middle text-nowrap text-center">
        <thead>
          <tr>
            <th scope="col" className="fw-normal">
              {t('title')}
            </th>
            <th scope="col" className="fw-normal">
              {t('comments')}
            </th>
            <th scope="col" className="fw-normal">
              {t('replies')}
            </th>
            <th scope="col" className="fw-normal">
              {t('views')}
            </th>
            <th scope="col" className="fw-normal">
              {t('created')}
            </th>
            <th scope="col" className="fw-normal">
              {t('time')}
            </th>
          </tr>
        </thead>
        <tbody>
          {items.map((item) => {
            return (
              <tr key={item.id}>
                <td className="text-nowrap text-md-wrap">
                  <PostName
                    item={item}
                    isTable
                    isJustifyContentCenter
                    isFwSemibold={false}
                  />
                </td>

                <td>{formatCount(item.details!.commentCount)}</td>

                <td>{formatCount(item.details!.replyCount)}</td>

                <td>{formatCount(item.details!.viewCount)}</td>

                <td>
                  <Link
                    href={`/users/${item.createdBy}`}
                    className="text-reset link-underline link-offset-3 link-underline-opacity-0 link-underline-opacity-100-hover"
                  >
                    {item.creatorAlias}
                  </Link>
                </td>

                <td>
                  <time
                    className={classNames(
                      item._contentUpdatedOnText ? false : 'invisible',
                    )}
                    dateTime={item.contentUpdatedOn}
                  >
                    {item._contentUpdatedOnText}
                  </time>
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
};

const LoadMoreBtn = ({
  isDisabled,
  isFetchingNextPage,
  onClickLoadMore = () => {},
}: {
  isDisabled?: boolean;
  isFetchingNextPage?: boolean;
  onClickLoadMore?: () => void;
}) => {
  return (
    <div className="row mt-5 mb-4 justify-content-center">
      <div className="col rounded py-4">
        <button
          onClick={onClickLoadMore}
          disabled={isFetchingNextPage && isDisabled}
          type="button"
          className="btn rounded-pill text-secondary-emphasis w-100"
        >
          {isFetchingNextPage ? (
            <>
              <span
                className="spinner-border spinner-border-sm me-2"
                role="status"
                aria-hidden="true"
              ></span>
              Loading...
            </>
          ) : (
            <i className="bi bi-three-dots"></i>
          )}
        </button>
      </div>
    </div>
  );
};
